//=============================================================================
//
// Copyright (C) 2007 Michael Coyle, Blue Toque
// http://www.BlueToque.ca/Products/CodeGeneration.html
// michael.coyle@BlueToque.ca
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// http://www.gnu.org/licenses/gpl.txt
//
//=============================================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;

namespace CodeGeneration.Generators
{
    /// <summary>
    /// This generates a Web Service Proxy directly from a type that contains a web service
    /// </summary>
    public class TypeProxyGenerator : BaseCodeGenerator
    {
        public TypeProxyGenerator(Type type, string uri, string path)
        {
            m_type = type;
            m_uri = uri;
        }

        Type m_type;
        string m_uri;
        private ServiceDescriptionImportStyle m_style = ServiceDescriptionImportStyle.Client;

        /// <summary>
        /// This is the workhorse method of the program. Given a web service type, 
        /// it generates a proxy class for it, strips out any excess types, and then 
        /// adds a few using statments to it. 
        /// </summary>
        /// <param name="type">The web service type</param>
        /// <param name="uri">The URL for the service that will be set in the constructor</param>
        private bool Compile()
        {
            try
            {
                // These next two lines do the generate the WSDL based on the web service class
                ServiceDescriptionReflector reflector = new ServiceDescriptionReflector();
                reflector.Reflect(m_type, m_uri);

                if (reflector.ServiceDescriptions.Count > 1)
                    throw new Exception(string.Format("Don't know how to deal with multiple service descriptions in {0}", m_type));

                // Now we take the WSDL service description and turn it into a proxy in CodeDOM form
                ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
                importer.AddServiceDescription(reflector.ServiceDescriptions[0], null, null);
                importer.Style = m_style;

                // Probably a good idea to make the namespace a command-line parameter, but hardcode it for now
                //CodeNamespace codeNamespace = new CodeNamespace("Integic.ePower.Psd.WebServices.Common.Proxies");
                CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
                codeCompileUnit.Namespaces.Add(CodeNamespace);

                ServiceDescriptionImportWarnings warnings = importer.Import(CodeNamespace, codeCompileUnit);

                // TODO: explicitly handle all of the warnings generated by the ServiceImporter
                if (warnings != 0)
                {
                    Trace.TraceError("Warnings: {1}", warnings);

                    string errorMessage;
                    switch (warnings)
                    {
                        case ServiceDescriptionImportWarnings.NoMethodsGenerated:
                            errorMessage = string.Format("Error: Web service at {0} does not contain any web methods", m_type.FullName);
                            throw new ApplicationException(errorMessage);
                        case ServiceDescriptionImportWarnings.NoCodeGenerated:
                            errorMessage = string.Format("Error: No code was generated for web service at {0}", m_type.FullName);
                            throw new ApplicationException(errorMessage);
                        default:
                            errorMessage = string.Format("Error: Unhandled error while generating code for web service {0} : {1}", m_type.FullName, warnings.ToString());
                            throw new ApplicationException(errorMessage);
                    }
                }

                if (!GenerateCode())
                    return false;

            }
            catch (Exception ex)
            {
                Errors.Add(new CompilerError(string.Empty, 0, 0, string.Empty, ex.Message));
                Trace.TraceError(ex.ToString());
                return false;
            }

            return true;

        }
    }
}
